package org.finesys.common.security.authentication.password;

import lombok.extern.slf4j.Slf4j;
import org.finesys.common.security.authentication.base.OAuth2ResourceOwnerBaseAuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;

import java.util.Map;

@Slf4j
public class OAuth2ResourceOwnerPasswordAuthenticationProvider extends OAuth2ResourceOwnerBaseAuthenticationProvider<OAuth2ResourceOwnerPasswordAuthenticationToken> {
    public OAuth2ResourceOwnerPasswordAuthenticationProvider(HttpSecurity httpSecurity) {
        super(httpSecurity);
    }

    @Override
    public UsernamePasswordAuthenticationToken buildToken(Authentication authentication, Map<String, Object> requestParameters) {
        String userName = (String) requestParameters.get(OAuth2ParameterNames.USERNAME);
        String password = (String) requestParameters.get(OAuth2ParameterNames.PASSWORD);
        return new UsernamePasswordAuthenticationToken(userName, password);
    }


    @Override
    public boolean supports(Class<?> authentication) {
        boolean supports = OAuth2ResourceOwnerPasswordAuthenticationToken.class.isAssignableFrom(authentication);
        if (log.isDebugEnabled()) {
            log.debug("supports  authentication=[{}] returning {}", authentication, supports);
        }
        return supports;
    }


    @Override
    public void checkClient(RegisteredClient registeredClient) {
        assert registeredClient != null;
        if (!registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.PASSWORD)) {
            throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
        }
    }
}
